package com.jrx.anytxn.param.service.product.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.constant.CommonContants;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.dto.product.InterestTableReq;
import com.jrx.anytxn.param.dto.product.InterestTableRes;
import com.jrx.anytxn.param.entity.PrInterestTable;
import com.jrx.anytxn.param.mapper.ext.ExtPrInterestTableMapper;
import com.jrx.anytxn.param.service.product.IInterestTableService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;

/**
 * 利息表 业务接口实现
 *
 * @author yx
 * @date 2019/5/28
 */
@Service
@CacheConfig(cacheNames = "INTEREST")
public class InterestTableServiceImpl implements IInterestTableService {
    private static final Logger logger = LoggerFactory.getLogger(InterestTableServiceImpl.class);
    @Resource
    private ExtPrInterestTableMapper extPrInterestTableMapper;

    @Autowired
    private ISegmentService segmentService;


    @Override
    public TxnPage<InterestTableRes> findAllPageByTenId(Integer pageNum, Integer pageSize, String tenantId) {
        Page<PrInterestTable> page = PageHelper.startPage(pageNum, pageSize, Constant.ORDER_BY_SORT);
        List<PrInterestTable> interestTableList = extPrInterestTableMapper.selectByTenId(tenantId);
        List<InterestTableRes> res = new LinkedList<>();
        if (interestTableList != null && !interestTableList.isEmpty()) {
            res = BeanMapping.copyList(interestTableList, InterestTableRes.class);
        }
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @Override
    public List<InterestTableRes> findAllByTenId(String tenantId) {
        List<PrInterestTable> interestTableList = extPrInterestTableMapper.selectByTenId(tenantId);
        List<InterestTableRes> res = new LinkedList<>();
        if (interestTableList != null && !interestTableList.isEmpty()) {
            res = BeanMapping.copyList(interestTableList, InterestTableRes.class);
        }
        return res;
    }

    @Override
    public InterestTableRes addInterestTable(InterestTableReq interestTableReq) throws TxnException {
        PrInterestTable prInterestTable = extPrInterestTableMapper.selectByTenIdAndInterestId(interestTableReq.getTenantId(), interestTableReq.getInterestId());
        if (prInterestTable != null) {
            logger.error(TxnRespCode.DATA_EXISTS.getMsg());
            throw new TxnException(TxnRespCode.DATA_EXISTS.getMsg());
        }
        PrInterestTable interestTable = BeanMapping.copy(interestTableReq, PrInterestTable.class);
        try {
            interestTable.setId(segmentService.getId(Constant.PR_INTEREST_TABLE));
        } catch (SegmentException e) {
            logger.error("主键生成错误", e);
            throw new TxnException(ErrorMsgConstant.ERROR_ID);
        }
        interestTable.setRecordVersionNumber(Constant.VERSION_NUMBER);
        extPrInterestTableMapper.insertSelective(interestTable);
        return BeanMapping.copy(interestTable, InterestTableRes.class);
    }

    @CacheEvict(key = "'interest_'+#interestTableReq.tenantId+'_'+#interestTableReq.interestId")
    @Override
    public InterestTableRes modifyInterestTable(InterestTableReq interestTableReq) throws TxnException {
        PrInterestTable prInterestTable = extPrInterestTableMapper.selectByTenIdAndInterestId(interestTableReq.getTenantId(), interestTableReq.getInterestId());
        if (prInterestTable == null) {
            logger.error(TxnRespCode.NO_DATA.getMsg());
            throw new TxnException(TxnRespCode.NO_DATA.getMsg());
        }
        PrInterestTable interestTable = BeanMapping.copy(interestTableReq, PrInterestTable.class);
        // 更新
        extPrInterestTableMapper.updateByTenIdAndInterestId(interestTable);
        return BeanMapping.copy(interestTable, InterestTableRes.class);

    }

    @CacheEvict(key = "'interest_'+#tenantId+'_'+#interestId")
    @Override
    public Boolean removeByTenIdAndInterestId(String tenantId, String interestId) throws TxnException {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(interestId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        int i = extPrInterestTableMapper.deleteByTenIdAndInterestId(tenantId, interestId);
        return i > 0;
    }

    @Override
    public InterestTableRes findByTenIdAndInterestId(String tenantId, String interestId) throws TxnException {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(interestId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        PrInterestTable interestTable = extPrInterestTableMapper.selectByTenIdAndInterestId(tenantId, interestId);
        return BeanMapping.copy(interestTable, InterestTableRes.class);
    }

    @Override
    public InterestTableRes findByInterestId(String interestId, String orgId, String tenantId) throws TxnException {
        PrInterestTable interestTable = extPrInterestTableMapper.selectByInterestId(interestId, tenantId);
        if (interestTable == null) {
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.NO_INTEREST_DATA));
        }
        return BeanMapping.copy(interestTable, InterestTableRes.class);
    }

    @Cacheable(key = "'interest_'+#tenantId+'_'+#interestId")
    @Override
    public PrInterestTable findInterestByInterestId(String interestId, String tenantId) throws TxnBizException {
        PrInterestTable interestTable = extPrInterestTableMapper.selectByInterestId(interestId, tenantId);
        if (interestTable == null) {
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.NO_INTEREST_DATA));
        }
        return interestTable;
    }

    /**
     * 日利率计算
     *
     * @param interestId
     * @param tenantId
     * @param businessDate
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getDailyRate(String interestId, String tenantId, Date businessDate) throws TxnBizException {
        PrInterestTable prInterestTable = this.findInterestByInterestId(interestId, tenantId);
        return this.getDailyRate(prInterestTable, businessDate);
    }

    /**
     * 日利率计算
     *
     * @param prInterestTable
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getDailyRate(PrInterestTable prInterestTable, Date businessDate) throws TxnBizException {

        BigDecimal baseRate = prInterestTable.getBaseRate();// 初始利率 若是月则不需要复杂计算

        //利率变动类型 不是固定利率   基础利率*调整利率百分比
        if (!Constant.INT_CHANGE_TYPE_FIXED.equals(prInterestTable.getInterestChangeType()) && prInterestTable.getBaseRatePercent() != null) {
            baseRate = baseRate.multiply(prInterestTable.getBaseRatePercent());
        }

        //年利率基础参数
        int yearBase = getYearBase(prInterestTable.getYearBase());

        // 月利率基础参数
        int monthBase = getMonthBase(prInterestTable.getMonthBase(), businessDate);

        // 0-年利率
        if (Constant.INT_TYPE_YEAR.equalsIgnoreCase(prInterestTable.getRateType())) {//初始是年利率
            baseRate = baseRate.divide(
                    BigDecimal.valueOf(yearBase), CommonContants.BIGDECIMAL_SCALE_7, BigDecimal.ROUND_HALF_UP);
        } else if (Constant.INT_TYPE_MONTH.equalsIgnoreCase(prInterestTable.getRateType())) {// 初始是月利率
            baseRate = baseRate.divide(
                    BigDecimal.valueOf(monthBase), CommonContants.BIGDECIMAL_SCALE_7, BigDecimal.ROUND_HALF_UP);
        }
        return baseRate;
    }

    /**
     * 月利率计算
     *
     * @param interestId
     * @param tenantId
     * @param businessDate
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getMonthRate(String interestId, String tenantId, Date businessDate) throws TxnBizException {
        PrInterestTable prInterestTable = this.findInterestByInterestId(interestId, tenantId);
        return this.getMonthRate(prInterestTable, businessDate);
    }

    /**
     * 月利率计算
     *
     * @param prInterestTable
     * @param businessDate
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getMonthRate(PrInterestTable prInterestTable, Date businessDate) throws TxnBizException {
        BigDecimal baseRate = prInterestTable.getBaseRate();// 初始利率 若是月则不需要复杂计算
        //利率变动类型 不是固定利率   基础利率*调整利率百分比
        if (!Constant.INT_CHANGE_TYPE_FIXED.equals(prInterestTable.getInterestChangeType()) && prInterestTable.getBaseRatePercent() != null) {
            baseRate = baseRate.multiply(prInterestTable.getBaseRatePercent());
        }
        //月利率基础参数
        int monthBase = getMonthBase(prInterestTable.getMonthBase(), businessDate);
        // 初始是年利率
        if (Constant.INT_TYPE_YEAR.equalsIgnoreCase(prInterestTable.getRateType())) {
            baseRate = baseRate.divide(
                    new BigDecimal(CommonContants.MONTH), CommonContants.BIGDECIMAL_SCALE_7, BigDecimal.ROUND_HALF_UP);
        } else if (Constant.INT_TYPE_DAILY.equalsIgnoreCase(prInterestTable.getRateType())) {//初始是天利率
            baseRate = baseRate.multiply(new BigDecimal(monthBase));
        }
        return baseRate;
    }

    /**
     * 年利率计算
     *
     * @param interestId
     * @param tenantId
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getYearRate(String interestId, String tenantId) throws TxnBizException {
        PrInterestTable prInterestTable = this.findInterestByInterestId(interestId, tenantId);
        return this.getYearRate(prInterestTable);
    }

    /**
     * 年利率计算
     *
     * @param prInterestTable
     * @return
     * @throws TxnBizException
     */
    @Override
    public BigDecimal getYearRate(PrInterestTable prInterestTable) throws TxnBizException {

        BigDecimal baseRate = prInterestTable.getBaseRate();// 初始利率 若是年则不需要复杂计算

        if (!Constant.INT_CHANGE_TYPE_FIXED.equals(prInterestTable.getInterestChangeType()) && prInterestTable.getBaseRatePercent() != null) {//利率变动类型 不是固定利率
            baseRate = baseRate.multiply(prInterestTable.getBaseRatePercent());//基础利率乘以调整利率百分比
        }
        //年利率基础参数
        int yearBase = getYearBase(prInterestTable.getYearBase());

        if (Constant.INT_TYPE_MONTH.equalsIgnoreCase(prInterestTable.getRateType())) {// 若初始是月利率
            baseRate = baseRate.multiply(new BigDecimal(CommonContants.MONTH));
        } else if (Constant.INT_TYPE_DAILY.equalsIgnoreCase(prInterestTable.getRateType())) {//初始是日利率
            baseRate = baseRate.multiply(new BigDecimal(yearBase));
        }
        return baseRate;
    }


    /**
     * 获取年利率基础天数
     *
     * @param yearBaseParam 年利率基础因子
     * @return 年利率基础天数
     */
    @Override
    public int getYearBase(String yearBaseParam) {
        switch (yearBaseParam) {
            case Constant.YEAR_360:
                return 360;
            case Constant.YEAR_366:
                GregorianCalendar gc = new GregorianCalendar();
                if (gc.isLeapYear(gc.get(GregorianCalendar.YEAR))) {
                    return 366;
                } else {
                    return 365;
                }
            default:
                return 365;
        }
    }

    /**
     * 获取月利率基础天数
     *
     * @param monthBaseParam 年利率基础因子
     * @return 年利率基础天数
     */
    @Override
    public int getMonthBase(String monthBaseParam, Date businessDate) {
        switch (monthBaseParam) {
            case Constant.MONTH_BASE_D:
                return DateUtils.getTotalDaysOfMonth(businessDate);
            default:
                return 30;
        }
    }
}
